package com.bandi.tharshesnows.persistence;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import com.bandi.tharshesnows.model.County;
import com.bandi.tharshesnows.model.Resort;
import com.bandi.tharshesnows.persistence.Metadata.LocalityMetadata;

public class LocalityDAO {

  private Database database;

  LocalityDAO(Database database) {
    super();
    this.database = database;
  }

  public Resort create(Resort locality) throws DAOException {
    try {
      SQLiteDatabase db = database.open();
      ContentValues values = new ContentValues();
      values.put(LocalityMetadata.COUNTY_ID, locality.getCounty().get_id());
      values.put(LocalityMetadata.NAME, locality.getName());
      values.put(LocalityMetadata.STARRED, locality.isStarred() ? 1 : 0);
      if (locality.getUpdated() != null) {
        values.put(LocalityMetadata.UPDATED, locality.getUpdated().getTime());
      }
      locality.set_id(db.insert(LocalityMetadata.TABLE_NAME, null, values));
      return locality;
    }
    catch (Throwable t) {
      throw new DAOException("Failed to create locality.", t);
    }
    finally {
      database.close();
    }
  }

  public List<Resort> getForCounty(County county) throws DAOException {
    try {
      SQLiteDatabase db = database.open();
      List<Resort> localities = new ArrayList<Resort>();
      Cursor cursor = db.query(LocalityMetadata.TABLE_NAME, LocalityMetadata.COLUMNS, LocalityMetadata.COUNTY_ID + "="
          + county.get_id(), null, null, null, null);
      cursor.moveToFirst();
      if (cursor.moveToFirst()) {
        do {
          localities.add(map(cursor, county));
        } while (cursor.moveToNext());
      }
      return localities;
    }
    catch (Throwable t) {
      throw new DAOException("Failed to get localities for: " + county.getName(), t);
    }
    finally {
      database.close();
    }
  }

  public Resort get(long id, County county) throws DAOException {
    try {
      SQLiteDatabase db = database.open();
      Cursor cursor = db.query(LocalityMetadata.TABLE_NAME, LocalityMetadata.COLUMNS,
          LocalityMetadata._ID + " = " + id, null, null, null, null);
      if (cursor.moveToFirst()) {
        return map(cursor, county);
      }
      else {
        return null;
      }
    }
    catch (Throwable t) {
      throw new DAOException("Failed to get locality.", t);
    }
    finally {
      database.close();
    }
  }

  public Resort get(String name, County county) throws DAOException {
    try {
      SQLiteDatabase db = database.open();
      Cursor cursor = db.query(LocalityMetadata.TABLE_NAME, LocalityMetadata.COLUMNS, LocalityMetadata.NAME + " = '"
          + name + "' AND " + LocalityMetadata.COUNTY_ID + " = " + county.get_id(), null, null, null, null);
      if (cursor.moveToFirst()) {
        return map(cursor, county);
      }
      else {
        return null;
      }
    }
    catch (Throwable t) {
      throw new DAOException("Failed to get locality.", t);
    }
    finally {
      database.close();
    }
  }

  public Resort update(Resort locality) throws DAOException {
    try {
      SQLiteDatabase db = database.open();
      ContentValues values = new ContentValues();
      values.put(LocalityMetadata.STARRED, locality.isStarred() ? 1 : 0);
      values.put(LocalityMetadata.UPDATED, locality.getUpdated().getTime());
      db.update(LocalityMetadata.TABLE_NAME, values, LocalityMetadata._ID + "=" + locality.get_id(), null);
      return locality;
    }
    catch (Throwable t) {
      throw new DAOException("Failed to update locality.", t);
    }
    finally {
      database.close();
    }
  }

  private Resort map(Cursor cursor, County county) {
    Resort locality = new Resort(county);
    locality.set_id(cursor.getLong(cursor.getColumnIndex(LocalityMetadata._ID)));
    locality.setName(cursor.getString(cursor.getColumnIndex(LocalityMetadata.NAME)));
    locality.setStarred(cursor.getInt(cursor.getColumnIndex(LocalityMetadata.STARRED)) == 1 ? true : false);
    locality.setUpdated(new Date(cursor.getLong(cursor.getColumnIndex(LocalityMetadata.UPDATED))));
    return locality;
  }

}
